package com.kurt.service.impl;

import com.kurt.dto.LoginRequest;
import com.kurt.dto.LoginResponse;
import com.kurt.dto.UserDTO;
import com.kurt.dto.create.UserCreateRequest;
import com.kurt.dto.query.UserQueryRequest;
import com.kurt.dto.update.UserUpdateRequest;
import com.kurt.entity.*;
import com.kurt.repository.*;
import com.kurt.service.DataPermissionService;
import com.kurt.service.UserService;
import com.kurt.util.DataPermissionUtil;
import com.kurt.util.JwtUtil;
import com.kurt.util.PasswordUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 * 实现用户相关的业务逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends BaseServiceImpl<SysUser, Long> implements UserService {

    private final SysUserRepository userRepository;
    private final SysUserExtensionRepository userExtensionRepository;
    private final SysUserRoleRepository userRoleRepository;
    private final SysRoleRepository roleRepository;
    private final SysMenuRepository menuRepository;
    private final SysOrganizationRepository organizationRepository;
    private final JwtUtil jwtUtil;
    private final DataPermissionService dataPermissionService;
    private final DataPermissionUtil dataPermissionUtil;

    @Override
    protected SysUserRepository getRepository() {
        return userRepository;
    }

    @Override
    protected SysUserRepository getSpecificationExecutor() {
        return userRepository;
    }

    @Override
    @Transactional
    public LoginResponse login(LoginRequest loginRequest) {
        log.info("用户登录请求: {}", loginRequest.getAccount());

        // 根据账号查找用户
        Optional<SysUser> userOpt = userRepository.findByAccountAndStatus(loginRequest.getAccount(), 1);
        if (userOpt.isEmpty()) {
            throw new RuntimeException("用户不存在或已禁用");
        }

        SysUser user = userOpt.get();

        // 验证密码
        if (!loginRequest.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 生成JWT令牌（包含组织ID）
        String token = jwtUtil.generateToken(user.getId(), user.getAccount(), user.getOrganizationId());

        // 构建登录响应
        LoginResponse response = new LoginResponse();
        response.setToken(token);
        response.setExpiresIn(jwtUtil.getExpirationDateFromToken(token).getTime());

        // 构建用户信息
        LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAccount(user.getAccount());
        userInfo.setRealName(user.getRealName());
        userInfo.setPhone(user.getPhone());
        userInfo.setOrganizationId(user.getOrganizationId());

        // 获取组织名称
        Optional<SysOrganization> orgOpt = organizationRepository.findById(user.getOrganizationId());
        if (orgOpt.isPresent()) {
            userInfo.setOrganizationName(orgOpt.get().getName());
        }

        // 获取用户角色
        List<SysRole> roles = roleRepository.findByUserId(user.getId());
        userInfo.setRoles(roles.stream().map(SysRole::getName).collect(Collectors.toList()));

        // 获取用户权限
        List<String> permissions = getUserPermissions(user.getId());
        userInfo.setPermissions(permissions);

        response.setUserInfo(userInfo);

        log.info("用户登录成功: {}", user.getAccount());
        return response;
    }

    @Override
    public boolean logout(String token) {
        // 这里可以实现令牌黑名单机制
        // 目前简单返回true
        log.info("用户登出: {}", jwtUtil.getUsernameFromToken(token));
        return true;
    }

    @Override
    @Transactional
    public UserDTO createUser(UserCreateRequest createRequest) {
        log.info("创建用户: {}", createRequest.getAccount());

        // 检查账号是否已存在
        if (userRepository.existsByAccount(createRequest.getAccount())) {
            throw new RuntimeException("账号已存在");
        }

        // 创建用户实体
        SysUser user = new SysUser();
        BeanUtils.copyProperties(createRequest, user);
        user.setPassword(PasswordUtil.encryptPassword(createRequest.getPassword()));
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        user = userRepository.save(user);

        // 创建用户扩展信息
        if (createRequest.getUserExtension() != null) {
            SysUserExtension extension = new SysUserExtension();
            extension.setId(user.getId());
            BeanUtils.copyProperties(createRequest.getUserExtension(), extension);
            extension.setCreateTime(LocalDateTime.now());
            extension.setUpdateTime(LocalDateTime.now());
            userExtensionRepository.save(extension);
        }

        // 分配角色
        if (createRequest.getRoleIds() != null && !createRequest.getRoleIds().isEmpty()) {
            assignRoles(user.getId(), createRequest.getRoleIds());
        }

        log.info("用户创建成功: {}", user.getAccount());
        return convertToUserDTO(user);
    }

    @Override
    @Transactional
    public UserDTO updateUser(UserUpdateRequest updateRequest) {
        log.info("更新用户: {}", updateRequest.getId());

        // 查找用户
        SysUser user = getById(updateRequest.getId());

        // 更新用户信息
        if (StringUtils.hasText(updateRequest.getRealName())) {
            user.setRealName(updateRequest.getRealName());
        }
        if (StringUtils.hasText(updateRequest.getPhone())) {
            user.setPhone(updateRequest.getPhone());
        }
        if (updateRequest.getStatus() != null) {
            user.setStatus(updateRequest.getStatus());
        }
        if (updateRequest.getOrganizationId() != null) {
            user.setOrganizationId(updateRequest.getOrganizationId());
        }
        if (StringUtils.hasText(updateRequest.getRemark())) {
            user.setRemark(updateRequest.getRemark());
        }
        user.setUpdateTime(LocalDateTime.now());

        // 保存用户
        user = userRepository.save(user);

        // 更新用户扩展信息
        if (updateRequest.getUserExtension() != null) {
            Optional<SysUserExtension> extensionOpt = userExtensionRepository.findById(user.getId());
            if (extensionOpt.isPresent()) {
                SysUserExtension extension = extensionOpt.get();
                BeanUtils.copyProperties(updateRequest.getUserExtension(), extension);
                extension.setUpdateTime(LocalDateTime.now());
                userExtensionRepository.save(extension);
            } else {
                // 创建新的扩展信息
                SysUserExtension extension = new SysUserExtension();
                extension.setId(user.getId());
                BeanUtils.copyProperties(updateRequest.getUserExtension(), extension);
                extension.setCreateTime(LocalDateTime.now());
                extension.setUpdateTime(LocalDateTime.now());
                userExtensionRepository.save(extension);
            }
        }

        // 更新角色
        if (updateRequest.getRoleIds() != null) {
            assignRoles(user.getId(), updateRequest.getRoleIds());
        }

        log.info("用户更新成功: {}", user.getAccount());
        return convertToUserDTO(user);
    }

    @Override
    public UserDTO getUserById(Long id) {
        SysUser user = getById(id);
        return convertToUserDTO(user);
    }

    @Override
    public Page<UserDTO> getUserPage(UserQueryRequest queryRequest) {
        // 构建分页参数
        Sort sort = Sort.by(Sort.Direction.fromString(queryRequest.getOrderDirection()), queryRequest.getOrderBy());
        Pageable pageable = PageRequest.of(queryRequest.getPageNum() - 1, queryRequest.getPageSize(), sort);

        // 构建查询条件
        Specification<SysUser> spec = buildUserSpecification(queryRequest);

        // 执行分页查询
        Page<SysUser> userPage = userRepository.findAll(spec, pageable);

        // 转换为DTO
        return userPage.map(this::convertToUserDTO);
    }

    @Override
    public List<UserDTO> getUserList(UserQueryRequest queryRequest) {
        // 构建查询条件
        Specification<SysUser> spec = buildUserSpecification(queryRequest);

        // 执行查询
        List<SysUser> users = userRepository.findAll(spec);

        // 转换为DTO
        return users.stream().map(this::convertToUserDTO).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public boolean deleteUser(Long id) {
        log.info("删除用户: {}", id);

        // 删除用户角色关联
        userRoleRepository.deleteByUserId(id);

        // 删除用户扩展信息
        userExtensionRepository.deleteById(id);

        // 删除用户
        userRepository.deleteById(id);

        log.info("用户删除成功: {}", id);
        return true;
    }

    @Override
    @Transactional
    public boolean deleteUsers(List<Long> ids) {
        log.info("批量删除用户: {}", ids);

        for (Long id : ids) {
            deleteUser(id);
        }

        log.info("批量删除用户成功: {}", ids);
        return true;
    }

    @Override
    @Transactional
    public boolean resetPassword(Long id, String newPassword) {
        log.info("重置用户密码: {}", id);

        SysUser user = getById(id);
        user.setPassword(PasswordUtil.encryptPassword(newPassword));
        user.setUpdateTime(LocalDateTime.now());
        userRepository.save(user);

        log.info("用户密码重置成功: {}", id);
        return true;
    }

    @Override
    @Transactional
    public boolean changePassword(Long id, String oldPassword, String newPassword) {
        log.info("修改用户密码: {}", id);

        SysUser user = getById(id);

        // 验证旧密码
        if (!PasswordUtil.verifyPassword(oldPassword, user.getPassword())) {
            throw new RuntimeException("旧密码错误");
        }

        // 设置新密码
        user.setPassword(PasswordUtil.encryptPassword(newPassword));
        user.setUpdateTime(LocalDateTime.now());
        userRepository.save(user);

        log.info("用户密码修改成功: {}", id);
        return true;
    }

    @Override
    @Transactional
    public boolean assignRoles(Long userId, List<Long> roleIds) {
        log.info("分配用户角色: userId={}, roleIds={}", userId, roleIds);

        // 删除现有角色关联
        userRoleRepository.deleteByUserId(userId);

        // 创建新的角色关联
        List<SysUserRole> userRoles = roleIds.stream()
                .map(roleId -> {
                    SysUserRole userRole = new SysUserRole();
                    userRole.setUserId(userId);
                    userRole.setRoleId(roleId);
                    userRole.setCreateTime(LocalDateTime.now());
                    return userRole;
                })
                .collect(Collectors.toList());

        userRoleRepository.saveAll(userRoles);

        log.info("用户角色分配成功: userId={}, roleIds={}", userId, roleIds);
        return true;
    }

    @Override
    public List<UserDTO.RoleDTO> getUserRoles(Long userId) {
        List<SysRole> roles = roleRepository.findByUserId(userId);
        return roles.stream()
                .map(role -> {
                    UserDTO.RoleDTO roleDTO = new UserDTO.RoleDTO();
                    BeanUtils.copyProperties(role, roleDTO);
                    return roleDTO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getUserPermissions(Long userId) {
        List<SysMenu> menus = menuRepository.findByUserId(userId);
        return menus.stream()
                .map(SysMenu::getPath)
                .filter(StringUtils::hasText)
                .collect(Collectors.toList());
    }

    @Override
    public UserDTO getUserByAccount(String account) {
        Optional<SysUser> userOpt = userRepository.findByAccount(account);
        return userOpt.map(this::convertToUserDTO).orElse(null);
    }

    @Override
    public boolean existsByAccount(String account) {
        return userRepository.existsByAccount(account);
    }

    @Override
    public boolean existsByPhone(String phone) {
        return userRepository.findByPhone(phone).isPresent();
    }

    @Override
    public List<UserDTO> getUsersByOrganizationId(Long organizationId, Long currentUserId) {
        // 数据权限过滤 - 只查询用户有权限的用户数据
        if (currentUserId == null) {
            log.warn("用户未登录，无法获取用户数据");
            return new ArrayList<>();
        }

        List<Long> authorizedUserIds = dataPermissionUtil.getAuthorizedResourceIds(currentUserId, "user");
        if (authorizedUserIds.isEmpty() || authorizedUserIds.contains(-1L)) {
            log.warn("用户{}没有用户数据权限", currentUserId);
            return new ArrayList<>();
        }

        // 先根据组织ID查询用户
        List<SysUser> users = userRepository.findByOrganizationId(organizationId);

        // 再根据数据权限过滤
        List<SysUser> filteredUsers = users.stream()
                .filter(user -> authorizedUserIds.contains(user.getId()))
                .collect(Collectors.toList());

        log.info("用户{}查询组织{}的用户，原始数量: {}, 权限过滤后数量: {}",
                currentUserId, organizationId, users.size(), filteredUsers.size());

        return filteredUsers.stream().map(this::convertToUserDTO).collect(Collectors.toList());
    }

    @Override
    public List<UserDTO> getUsersByRoleId(Long roleId, Long currentUserId) {
        // 数据权限过滤 - 只查询用户有权限的用户数据
        if (currentUserId == null) {
            log.warn("用户未登录，无法获取用户数据");
            return new ArrayList<>();
        }

        List<Long> authorizedUserIds = dataPermissionUtil.getAuthorizedResourceIds(currentUserId, "user");
        if (authorizedUserIds.isEmpty() || authorizedUserIds.contains(-1L)) {
            log.warn("用户{}没有用户数据权限", currentUserId);
            return new ArrayList<>();
        }

        // 先根据角色ID查询用户
        List<SysUser> users = userRepository.findByRoleId(roleId);

        // 再根据数据权限过滤
        List<SysUser> filteredUsers = users.stream()
                .filter(user -> authorizedUserIds.contains(user.getId()))
                .collect(Collectors.toList());

        log.info("用户{}查询角色{}的用户，原始数量: {}, 权限过滤后数量: {}",
                currentUserId, roleId, users.size(), filteredUsers.size());

        return filteredUsers.stream().map(this::convertToUserDTO).collect(Collectors.toList());
    }

    /**
     * 构建用户查询条件
     *
     * @param queryRequest 查询请求
     * @return 查询条件
     */
    private Specification<SysUser> buildUserSpecification(UserQueryRequest queryRequest) {
        return (root, query, cb) -> {
            List<jakarta.persistence.criteria.Predicate> predicates = new ArrayList<>();

            // 数据权限过滤 - 只查询用户有权限的用户数据
            Long currentUserId = queryRequest.getLoginUserId();
            if (currentUserId != null) {
                List<Long> authorizedUserIds = dataPermissionUtil.getAuthorizedResourceIds(currentUserId, "user");
                predicates.add(root.get("id").in(authorizedUserIds));
            }

            // 账号模糊查询
            if (StringUtils.hasText(queryRequest.getAccount())) {
                predicates.add(cb.like(root.get("account"), "%" + queryRequest.getAccount() + "%"));
            }

            // 真实姓名模糊查询
            if (StringUtils.hasText(queryRequest.getRealName())) {
                predicates.add(cb.like(root.get("realName"), "%" + queryRequest.getRealName() + "%"));
            }

            // 手机号模糊查询
            if (StringUtils.hasText(queryRequest.getPhone())) {
                predicates.add(cb.like(root.get("phone"), "%" + queryRequest.getPhone() + "%"));
            }

            // 状态查询
            if (queryRequest.getStatus() != null) {
                predicates.add(cb.equal(root.get("status"), queryRequest.getStatus()));
            }

            // 组织ID查询
            if (queryRequest.getOrganizationId() != null) {
                predicates.add(cb.equal(root.get("organizationId"), queryRequest.getOrganizationId()));
            }

            // 创建时间范围查询
            if (StringUtils.hasText(queryRequest.getCreateTimeStart())) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeStart())));
            }
            if (StringUtils.hasText(queryRequest.getCreateTimeEnd())) {
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
                        LocalDateTime.parse(queryRequest.getCreateTimeEnd())));
            }

            return cb.and(predicates.toArray(new jakarta.persistence.criteria.Predicate[0]));
        };
    }

    /**
     * 转换用户实体为DTO
     *
     * @param user 用户实体
     * @return 用户DTO
     */
    private UserDTO convertToUserDTO(SysUser user) {
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user, userDTO);

        // 获取组织名称
        Optional<SysOrganization> orgOpt = organizationRepository.findById(user.getOrganizationId());
        if (orgOpt.isPresent()) {
            userDTO.setOrganizationName(orgOpt.get().getName());
        }

        // 获取用户扩展信息
        Optional<SysUserExtension> extensionOpt = userExtensionRepository.findById(user.getId());
        if (extensionOpt.isPresent()) {
            UserDTO.UserExtensionDTO extensionDTO = new UserDTO.UserExtensionDTO();
            BeanUtils.copyProperties(extensionOpt.get(), extensionDTO);
            userDTO.setUserExtension(extensionDTO);
        }

        // 获取用户角色
        List<UserDTO.RoleDTO> roles = getUserRoles(user.getId());
        userDTO.setRoles(roles);

        return userDTO;
    }
}
